<template>
    <div class="page_root" :key="queryUpdateFlag" data-page-name="经营看板" data-page-identification="u_fqj38a73v0">
        <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
            <!-- begin vid_pwix3i6a8b 自定义模板_r3koyasnpg -->
            <!--      里程碑进度表弹窗-->
            <a-modal
                :visible="ftfState.modalVisible"
                title="总体经营仪表盘"
                width="80%"
                centered
                :footer="null"
                @cancel="ftfState.modalVisible = false"
                :mask-closable="false"
                destroy-on-close
            >
                <div class="search-radio">
                    <a-radio-group v-model:value="ftfState.radioValue" button-style="solid">
                        <a-radio-button value="全部">全部</a-radio-button>
                        <a-radio-button value="基础信息">基础信息</a-radio-button>
                        <a-radio-button value="项目阶段">项目阶段</a-radio-button>
                        <a-radio-button value="其他">其他</a-radio-button>
                    </a-radio-group>
                </div>
                <div class="kb-table-box-new">
                    <a-table
                        :columns="filteredColumns"
                        :dataSource="ftfState.dataSource"
                        :scroll="{ x: '1000px', y: 500 }"
                        :pagination="false"
                        :loading="ftfState.tableLoading"
                        bordered
                        @resizeColumn="handleResizeColumn"
                        :showSorterTooltip="false"
                        @change="handleTableChange"
                        ref="tableRef"
                    >
                        <template #headerCell="{ column, title }">
                            <template v-if="['进展', '问题&风险', '预计开始', '预计结束'].includes(title)">
                                <div class="text-line-div">{{ title }}</div>
                            </template>
                            <template v-if="title === '项目状态'">
                                <div class="text-line-div">
                                    {{ title }}
                                </div>
                            </template>
                            <template v-if="title === '工厂名称'">
                                <div class="text-line-div">
                                    {{ title }}
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'riskLevel'">
                                <span>
                                    {{ title }}
                                    <a-tooltip>
                                        <template #title>
                                            <p class="risk-level-tool-tip">风险等级划分：</p>
                                            <p class="risk-level-tool-tip">1、保底；</p>
                                            <p class="risk-level-tool-tip">2、略有风险；</p>
                                            <p class="risk-level-tool-tip">3、需要冲刺；</p>
                                            <p class="risk-level-tool-tip">4、暂不强推</p>
                                        </template>
                                        <question-circle-outlined />
                                    </a-tooltip>
                                </span>
                            </template>
                        </template>

                        <template #bodyCell="{ record, text, column, index }">
                            <template v-if="column.fieldType !== 'FILE' && column.fieldType">
                                <div class="db-click" @dblclick="showEditStatistics(column, record, index)">{{
                                    text
                                }}</div>
                            </template>
                            <template v-if="column.fieldType === 'FILE'">
                                <div class="file-div" @dblclick="showEditStatistics(column, record, index)">
                                    <template v-if="text">
                                        <div v-for="(item, index) in JSON.parse(text)" :key="item.name">
                                            <a-dropdown>
                                                <a :title="item.name">{{ item.name }}</a>
                                                <template #overlay>
                                                    <a-menu>
                                                        <a-menu-item>
                                                            <a-button
                                                                type="link"
                                                                size="small"
                                                                :disabled="!item.type.startsWith('image')"
                                                                @click="viewImage(item.url)"
                                                                >预览</a-button
                                                            >
                                                        </a-menu-item>
                                                        <a-menu-item>
                                                            <a-button
                                                                type="link"
                                                                size="small"
                                                                @click="downLoadFile(item)"
                                                                >下载</a-button
                                                            >
                                                        </a-menu-item>
                                                    </a-menu>
                                                </template>
                                            </a-dropdown>
                                        </div>
                                    </template>
                                    <template v-else>
                                        <div class="file-div"></div>
                                    </template>
                                </div>
                            </template>

                            <template v-if="['项目阶段'].includes(column.title)">
                                <div class="db-click" @dblclick="changeData(record, index)">{{ text }}</div>
                            </template>
                            <template v-if="column.dataIndex === 'progress'">
                                <div class="progress-click" @dblclick="changeData(record, index)">
                                    <a-tooltip :overlay-style="overStyle" v-if="record.progress">
                                        <template #title>{{ record.progress }}</template
                                        ><div class="omit-div">{{ text }} </div>
                                    </a-tooltip>
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'question'">
                                <div class="question-div" @dblclick="changeData(record, index)">
                                    <a-tooltip :overlay-style="overStyle" v-if="record.question">
                                        <template #title
                                            >{{ record.question }}【 {{ record.operator }}】【{{
                                                record.operateTime
                                            }}】</template
                                        ><div class="omit-div-question"
                                            ><span v-if="record.question"
                                                >{{ text }}【 {{ record.operator }}】【{{ record.operateTime }}】</span
                                            ></div
                                        >
                                    </a-tooltip>
                                    <!--                                    <div class="plus-icon" @click="handleAddLhwt"><PlusCircleOutlined /></div>-->
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'productionPlan'">
                                <div class="productionPlan-div">
                                    <a-tooltip :overlay-style="overStyle" v-if="record.productionPlan">
                                        <template #title>{{ text }}</template
                                        ><div class="omit-div-productionPlan" v-if="text">{{ text }}</div>
                                    </a-tooltip>
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'customerRelationship'">
                                <div class="customerRelationship-div">
                                    <a-tooltip :overlay-style="overStyle" v-if="record.customerRelationship">
                                        <template #title>{{ text }}</template
                                        ><div class="omit-div-customerRelationship"
                                            ><span v-if="text">{{ text }}</span></div
                                        >
                                    </a-tooltip>
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'count'">
                                {{ index + 1 }}
                            </template>
                            <template
                                v-if="
                                    [
                                        'modelExpectStartTime',
                                        'modelExpectEndTime',
                                        'testRunExpectStartTime',
                                        'testRunExpectEndTime',
                                        'runExpectStartTime',
                                        'runExpectEndTime',
                                        'checkExpectStartTime',
                                        'checkExpectEndTime',
                                        'verifyExpectStartTime',
                                        'verifyExpectEndTime'
                                    ].includes(column.dataIndex)
                                "
                            >
                                <div class="db-click" @dblclick="changeData(record, index)">{{ text }}</div>
                            </template>
                            <template v-if="column.dataIndex === 'supportors'">
                                <div class="support-div" :title="text" @dblclick="changeData(record, index)">{{
                                    text
                                }}</div>
                            </template>
                            <template v-if="column.dataIndex === 'projectStatus'">
                                <div
                                    v-if="record.projectStatus === '进行中'"
                                    class="db-click"
                                    @dblclick="changeData(record, index)"
                                    style="color: #3875ff"
                                    >{{ text }}</div
                                >
                                <div
                                    v-if="record.projectStatus === '准备'"
                                    class="db-click"
                                    @dblclick="changeData(record, index)"
                                    style="color: #ffa940"
                                    >{{ text }}</div
                                >
                                <div
                                    v-if="record.projectStatus === '完成'"
                                    class="db-click"
                                    @dblclick="changeData(record, index)"
                                    style="color: green"
                                    >{{ text }}</div
                                >
                                <div
                                    v-if="!record.projectStatus"
                                    class="db-click"
                                    @dblclick="changeData(record, index)"
                                    >{{ text }}</div
                                >
                            </template>
                            <template v-if="column.dataIndex === 'projectShortName'">
                                <div class="db-click-name" @dblclick="changeData(record, index)">{{ text }}</div>
                            </template>
                        </template>
                    </a-table>
                </div>
            </a-modal>

            <!--      里程碑进度表弹窗-->
            <!--      里程碑进度表弹窗-->
            <a-modal
                :visible="ftfState.detailVisible"
                title=""
                width="1200px"
                centered
                :footer="null"
                @cancel="ftfState.detailVisible = false"
                :mask-closable="false"
                destroy-on-close
                :body-style="{
                    padding: '0'
                }"
            >
                <div class="modal-body">
                    <!--                  成本统计顶部区域-->

                    <div class="modal-top" v-if="typeSelectIndex === 2">
                        <div class="modal-top-left">
                            <div class="left-top">
                                <div class="left-top-img"></div>
                                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
                            </div>
                            <div class="left-bottom">
                                <div class="bottom-left">
                                    <div class="bottom-left-item">
                                        <div class="title">启动时间：</div>
                                        <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                                    </div>
                                    <div class="bottom-left-item">
                                        <div class="title">预计验收：</div>
                                        <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                                    </div>
                                    <div class="bottom-left-item">
                                        <div class="title">项目阶段：</div>
                                        <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                                    </div>
                                </div>
                                <div class="bottom-right">
                                    <div class="route"></div>
                                    <div class="bottom-right-item">
                                        <div class="title">成本基准：</div>
                                        <div class="msg">{{ ftfState.dataSource.costBase }}人天</div>
                                    </div>
                                    <div class="bottom-right-item">
                                        <div class="title">实际成本：</div>
                                        <div class="msg">{{ ftfState.dataSource.costActual }}人天</div>
                                    </div>
                                    <div class="bottom-right-item">
                                        <div
                                            class="title"
                                            :style="getCostColor(ftfState.dataSource.costDeviation, true)"
                                            >成本偏差：</div
                                        >
                                        <div
                                            class="msg"
                                            :style="getCostColor(ftfState.dataSource.costDeviation, false)"
                                            >{{ getCostDiffer() }}</div
                                        >
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="modal-top-right">
                            <div class="right-top">
                                <div class="right-top-img"></div>
                                <div class="right-top-msg">{{ ftfState.dataSource.areaName }}</div>
                            </div>
                            <div class="right-bottom">
                                <div class="bottom-right-item">
                                    <div class="title">合计成本基准：</div>
                                    <div class="msg">{{ ftfState.dataSource.totalCostBase }}人天</div>
                                </div>
                                <div class="bottom-right-item">
                                    <div class="title">累计实际成本：</div>
                                    <div class="msg">{{ ftfState.dataSource.totalCostActual }}人天</div>
                                </div>
                                <div class="bottom-right-item">
                                    <div
                                        class="title"
                                        :style="getTotalCostColor(ftfState.dataSource.totalCostDeviation, true)"
                                        >累计成本偏差：</div
                                    >
                                    <div
                                        class="msg"
                                        :style="getTotalCostColor(ftfState.dataSource.totalCostDeviation, false)"
                                        >{{ getOverExpenditure(ftfState.dataSource.totalCostDeviation) }}</div
                                    >
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--                  成本统计顶部区域-->
                    <!--                  任务完成顶部区域-->
                    <div class="modal-top-0" v-if="typeSelectIndex === 0">
                        <div class="modal-top-left-0">
                            <div class="left-top-0">
                                <div class="left-top-img"></div>
                                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
                            </div>
                            <div class="left-bottom-0">
                                <div class="new-bottom">
                                    <div class="bottom-left-0">
                                        <div class="bottom-left-item">
                                            <div class="title">启动时间：</div>
                                            <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                                        </div>
                                        <div class="bottom-left-item">
                                            <div class="title">预计验收：</div>
                                            <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                                        </div>
                                        <div class="bottom-left-item">
                                            <div class="title">项目阶段：</div>
                                            <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                                        </div>
                                    </div>
                                    <div class="bottom-right-0">
                                        <div class="route-0"></div>
                                        <div class="bottom-right-item">
                                            <div class="title">计划周期：</div>
                                            <div class="msg">{{ ftfState.dataSource.periodBase }}天</div>
                                        </div>
                                        <div class="bottom-right-item">
                                            <div class="title">实际周期：</div>
                                            <div class="msg">{{ ftfState.dataSource.periodActual }}天</div>
                                        </div>
                                        <div class="bottom-right-item">
                                            <div
                                                class="title"
                                                :style="getReferenceColor(ftfState.dataSource.periodDeviation, true)"
                                                >进度偏差：</div
                                            >
                                            <div
                                                class="msg"
                                                :style="getReferenceColor(ftfState.dataSource.periodDeviation, false)"
                                                >{{ getTaskStatus(ftfState.dataSource.periodDeviation) }}</div
                                            >
                                        </div>
                                    </div>
                                </div>
                                <div class="bottom-right-last-0">
                                    <div class="bottom-right-item">
                                        <div class="title">主要风险：</div>
                                        <div class="msg">{{ ftfState.dataSource.mainRisk || '--' }}</div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="modal-top-right-0">
                            <div class="right-top-0">
                                <div class="right-top-img"></div>
                                <div class="right-top-msg-0">{{ ftfState.dataSource.areaName }}</div>
                            </div>
                            <div class="right-bottom-0">
                                <div class="bottom-right-item-0">
                                    <div class="title">合计周期基准：</div>
                                    <div class="msg">{{ ftfState.dataSource.totalPeriodBase }}天</div>
                                </div>
                                <div class="bottom-right-item-0">
                                    <div class="title">累计实际周期：</div>
                                    <div class="msg">{{ ftfState.dataSource.totalPeriodActual }}天</div>
                                </div>
                                <div class="bottom-right-item-0">
                                    <div
                                        class="title"
                                        :style="getTotalReferenceColor(ftfState.dataSource.totalPeriodDeviation, true)"
                                        >累计周期偏差：</div
                                    >
                                    <div
                                        class="msg"
                                        :style="getTotalReferenceColor(ftfState.dataSource.totalPeriodDeviation, false)"
                                        >{{ getTotalTaskStatus(ftfState.dataSource.totalPeriodDeviation) }}</div
                                    >
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--                  任务完成顶部区域-->
                    <!--                  资源投入顶部内容-->
                    <div class="modal-top" v-if="typeSelectIndex === 1">
                        <div class="modal-top-left">
                            <div class="left-top">
                                <div class="left-top-img"></div>
                                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
                            </div>
                            <div class="left-bottom">
                                <div class="bottom-left">
                                    <div class="bottom-left-item">
                                        <div class="title">启动时间：</div>
                                        <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                                    </div>
                                    <div class="bottom-left-item">
                                        <div class="title">预计验收：</div>
                                        <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                                    </div>
                                    <div class="bottom-left-item">
                                        <div class="title">项目阶段：</div>
                                        <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                                    </div>
                                </div>
                                <div class="bottom-right">
                                    <div class="route"></div>
                                    <div class="bottom-right-item">
                                        <div class="title" :style="getNameColor(ftfState.dataSource.pmDevition)"
                                            >项目经理：</div
                                        >
                                        <div class="msg" :style="getNameColor(ftfState.dataSource.pmDevition)">
                                            {{ ftfState.dataSource.pmName
                                            }}{{
                                                ftfState.dataSource.pmFactoryNumber > 1
                                                    ? '(' + '兼' + ftfState.dataSource.pmFactoryNumber + ')'
                                                    : ''
                                            }}</div
                                        >
                                    </div>
                                    <div class="bottom-right-item">
                                        <div class="title" :style="getNameColor(ftfState.dataSource.expertDevition)"
                                            >业务专家：</div
                                        >
                                        <div class="msg" :style="getNameColor(ftfState.dataSource.expertDevition)"
                                            >{{ ftfState.dataSource.businessExpert
                                            }}{{
                                                ftfState.dataSource.expertFactoryNumber > 1
                                                    ? '(' + '兼' + ftfState.dataSource.expertFactoryNumber + ')'
                                                    : ''
                                            }}</div
                                        >
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="modal-top-right">
                            <div class="right-top">
                                <div class="right-top-img"></div>
                                <div class="right-top-msg">{{ ftfState.dataSource.areaName }}</div>
                            </div>
                            <div class="right-bottom">
                                <div class="bottom-right-item">
                                    <div class="title">项目总监：</div>
                                    <div class="msg">{{ ftfState.dataSource.directorFactoryNumber }}</div>
                                </div>
                                <div class="bottom-right-item">
                                    <div class="title" :style="getNameColor(ftfState.dataSource.pmDevition)"
                                        >项目经理：</div
                                    >
                                    <div class="msg" :style="getNameColor(ftfState.dataSource.pmDevition)"
                                        >{{ ftfState.dataSource.pmAreaNumber
                                        }}{{
                                            ftfState.dataSource.pmAreaExtraNumber > ftfState.dataSource.pmAreaNumber
                                                ? '(' + '兼' + ftfState.dataSource.pmAreaExtraNumber + ')'
                                                : ''
                                        }}</div
                                    >
                                </div>
                                <div class="bottom-right-item">
                                    <div class="title" :style="getNameColor(ftfState.dataSource.expertDevition)"
                                        >业务专家：</div
                                    >
                                    <div class="msg" :style="getNameColor(ftfState.dataSource.expertDevition)"
                                        >{{ ftfState.dataSource.expertAreaNumber
                                        }}{{
                                            ftfState.dataSource.expertAreaExtraNumber >
                                            ftfState.dataSource.expertAreaNumber
                                                ? '(' + '兼' + ftfState.dataSource.expertAreaExtraNumber + ')'
                                                : ''
                                        }}</div
                                    >
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--                  资源投入顶部内容-->
                    <div class="kb-table-box">
                        <div class="inner-table">
                            <div class="inner-top-main">
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">区域：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.areaName }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">项目经理：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.pmName }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">项目支持：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.supportors }}</div>
                                    </div>
                                </div>
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">工厂名称：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.projectShortName
                                        }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">熟料算法：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.clinkerAlgorithmExpert
                                        }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">正式运行持续天数：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.runDays }}</div>
                                    </div>
                                </div>
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">批次：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.batch }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">水泥算法：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.cementAlgorithmExpert
                                        }}</div>
                                    </div>

                                    <div class="item-son">
                                        <div class="title">综合样20次：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.comprehensiveSample
                                        }}</div>
                                    </div>
                                </div>
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">产品类型：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.productType }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">项目阶段：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.milepostName }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">降本空间：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.expectedCostReduction
                                        }}</div>
                                    </div>
                                </div>
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">项目总监：</div>
                                        <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.projectDirector
                                        }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">项目状态：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.projectStatus }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">商务：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.preSaleManager }}</div>
                                    </div>
                                </div>
                                <div class="inner-top-item">
                                    <div class="item-son">
                                        <div class="title">水泥专家：</div>
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.businessExpert }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title">
                                            <a-tooltip>
                                                <template #title>
                                                    <p class="risk-level-tool-tip">风险等级划分：</p>
                                                    <p class="risk-level-tool-tip">1、保底；</p>
                                                    <p class="risk-level-tool-tip">2、略有风险；</p>
                                                    <p class="risk-level-tool-tip">3、需要冲刺；</p>
                                                    <p class="risk-level-tool-tip">4、暂不强推</p></template
                                                >
                                                <QuestionCircleOutlined /> </a-tooltip
                                            >风险等级：</div
                                        >
                                        <div class="msg">{{ ftfState.dataSource.projectProgress?.riskLevel }}</div>
                                    </div>
                                    <div class="item-son">
                                        <div class="title"></div>
                                        <div class="msg"></div>
                                    </div>
                                </div>
                            </div>
                            <div class="inner-row">
                                <div class="title">进展：</div>
                                <div class="msg">
                                    <div
                                        v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.progress
                                        )"
                                    >
                                        {{ item?.trim() }}
                                    </div></div
                                >
                            </div>
                            <div class="inner-row">
                                <div class="title">问题&风险：</div>
                                <div class="msg">
                                    <div
                                        v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.question
                                        )"
                                    >
                                        {{ item?.trim() }}
                                    </div>
                                </div>
                            </div>
                            <div class="inner-row">
                                <div class="title">生产计划：</div>
                                <div class="msg">{{ ftfState.dataSource.projectProgress?.productionPlan }}</div>
                            </div>
                            <div class="inner-row">
                                <div class="title">客情关系：</div>
                                <div class="msg">
                                    <div
                                        v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.customerRelationship
                                        )"
                                    >
                                        {{ item?.trim() }}
                                    </div>
                                </div>
                            </div>
                            <div class="inner-bottom"></div>
                            <a-table
                                style="margin-top: 8px"
                                :columns="columnState.newColumns"
                                :dataSource="ftfState.dataSource.timeList"
                                :scroll="{ x: '1000px', y: 700 }"
                                :pagination="false"
                                :loading="ftfState.tableLoading"
                                bordered
                                @resizeColumn="handleResizeColumn"
                                :showSorterTooltip="false"
                                @change="handleTableChange"
                                ref="tableRef"
                            />
                        </div>
                    </div>
                </div>
            </a-modal>

            <!--      里程碑进度表弹窗-->
            <div class="main-content" id="mainContent">
                <div class="top-title">
                    <span>经营地图看板</span>
                </div>
                <ul class="legend" v-if="typeSelectIndex === 0 || typeSelectIndex === 1">
                    <li @click="onChangelegends(0)" :class="{ gray: legendsDot[0] }">
                        <i class="img icon icon-green"></i>
                        偏差度20%以内
                    </li>
                    <li @click="onChangelegends(1)" :class="{ gray: legendsDot[1] }">
                        <i class="img icon icon-yellow"></i>
                        {{ typeSelectIndex === 0 ? '偏差度21%-40%' : '偏差度21%-50%' }}
                    </li>
                    <li @click="onChangelegends(2)" :class="{ gray: legendsDot[2] }">
                        <i class="img icon icon-red"></i>
                        {{ typeSelectIndex === 0 ? '偏差度40%以上' : '偏差度50%以上' }}
                    </li>
                </ul>
                <ul class="legend" v-else>
                    <li @click="onChangelegends(0)" :class="{ gray: legendsDot[0] }">
                        <i class="img icon icon-green"></i>
                        未超支
                    </li>
                    <li @click="onChangelegends(2)" :class="{ gray: legendsDot[2] }">
                        <i class="img icon icon-red"></i>
                        超支
                    </li>
                </ul>
                <div class="content">
                    <div class="left-geo">
                        <ul class="typeSels">
                            <li
                                v-for="(item, index) in typeList"
                                :key="index"
                                @click="onChangeType(index)"
                                :class="{ action: index === typeSelectIndex }"
                                >{{ item.itemName }}</li
                            >
                            <div class="priority-div">
                                <a-form-item label="优先级">
                                    <a-select
                                        style="width: 100px"
                                        v-model:value="newState.priority"
                                        :allow-clear="false"
                                        @change="changeSymbelSize"
                                        :options="[
                                            {
                                                label: '全部',
                                                value: '全部'
                                            },
                                            {
                                                label: '高',
                                                value: '高'
                                            },
                                            {
                                                label: '中',
                                                value: '中'
                                            },
                                            {
                                                label: '低',
                                                value: '低'
                                            }
                                        ]"
                                        allow-clear
                                        placeholder="请选择"
                                    />
                                </a-form-item>
                            </div>
                        </ul>

                        <div class="proAreaSels">
                            <ul :class="{ unexpend: !expends.pro }">
                                <div class="name" @click="onExpends('pro')">
                                    <i class="arrow-right icon"></i>
                                    <i class="img icon show-active icon-pro-sel"></i>
                                    <i class="img icon hide-active icon-pro"></i>

                                    产品线
                                </div>
                                <li
                                    v-for="(item, index) in proList"
                                    :key="index"
                                    @click="onChangeProLines(index)"
                                    :class="{
                                        active: index === proSelectIndex,
                                        disabled: index > 0 && (typeSelectIndex === 1 || typeSelectIndex === 2)
                                    }"
                                >
                                    <i class="img icon show-active icon-data-sel"></i>
                                    <i class="img icon hide-active icon-data"></i>
                                    {{ item.itemName }}
                                </li>
                            </ul>
                            <ul :class="{ unexpend: !expends.area }">
                                <div class="name" @click="onExpends('area')">
                                    <i class="arrow-right icon"></i>
                                    <i class="img icon show-active icon-area-sel"></i>
                                    <i class="img icon hide-active icon-area"></i>
                                    区域
                                </div>
                                <li
                                    v-for="(item, index) in areaList"
                                    :key="index"
                                    :class="{ active: index === areaSelIndex }"
                                >
                                    <i class="img icon show-active icon-data-sel"></i>
                                    <i class="img icon hide-active icon-data"></i>
                                    <span style="cursor: pointer; width: 120px" @click="onChangeArea(index)">{{
                                        item.itemName
                                    }}</span>
                                    <i
                                        class="img icon show-active icon-more-sel"
                                        style="margin-left: 10px; cursor: pointer"
                                        @click="getLcbData(null, '水泥配料', item.itemName)"
                                    ></i>
                                    <i
                                        class="img icon hide-active icon-more"
                                        style="margin-left: 10px; cursor: pointer"
                                        @click="getLcbData(null, '水泥配料', item.itemName)"
                                    ></i>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="echarts-content" :style="mainStyle">
                        <div class="img china-map-bg"></div>
                        <!--        <img src="http://10.40.0.33:9001/file-storage/487396325012760576-source.svg" class="china-map-bg" alt="" />-->
                        <a-spin :spinning="loadingStatus" tip="数据正在加载...">
                            <div class="echarts-main" id="echarts-chinamap"></div>
                        </a-spin>
                    </div>
                </div>
            </div>

            <!-- end vid_pwix3i6a8b 自定义模板_r3koyasnpg -->
            <!-- begin vid_z354kcjic1 图片_7j0nyi479u -->
            <al-image
                v-if="false"
                class="vid_z354kcjic1"
                :emptyImgSrc="''"
                :src="vid_z354kcjic1_props.src"
            />
            <!-- end vid_z354kcjic1 图片_7j0nyi479u -->
            <!-- begin vid_crznpxme1j 图片_f7l2frg8h7 -->
            <al-image
                v-if="false"
                class="vid_crznpxme1j"
                :emptyImgSrc="''"
                :src="vid_crznpxme1j_props.src"
            />
            <!-- end vid_crznpxme1j 图片_f7l2frg8h7 -->
        </a-spin>
    </div>
</template>
<script setup lang="tsx">
    import {
        h,
        ref,
        reactive,
        toRaw,
        markRaw,
        watch,
        computed,
        onBeforeMount,
        onMounted,
        onBeforeUnmount,
        onUnmounted,
        onActivated,
        onDeactivated
    } from 'vue'
    import { useRoute, useRouter } from 'vue-router'
    const router = useRouter()
    const route = useRoute()
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios'
    import {
        cloneDeep,
        localGet,
        merge,
        getDifferenceArray,
        traversalTreeStructure,
        checkCaseCondition,
        renderStringInTemplate,
        handleBreadcrumbJump,
        throttle,
        permission,
        getComponentParamsValue
    } from '@/utils/index'
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is'
    import dayjs from 'dayjs'
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart'
    import { message, notification, Modal } from 'ant-design-vue'
    import {
        propertyFormatByNumber,
        propertyFormatByPercentage,
        propertyFormatByDate,
        parseSubFromDataList
    } from '@/utils/format'
    import colorTheme from '@/design/custom-theme.json'
    /*** PUBLISH_EXEGESIS ***
 import UserTableRecords from '@/model/UserTableRecords';
 import { getAppBaseUrl } from '@/utils/index';
 import { sendToken } from "@/hooks/useIframeToken";
 import { useSystemStore } from "@/store/modules/system";
 const systemStore = useSystemStore();
 *** PUBLISH_EXEGESIS ***/

    // 获取传入的流程ID和组件参数
    const props = defineProps({
        'processInstanceId': {
            type: [String, Number, Boolean],
            default: undefined
        }
    })
    const immediateWatch = (source, callback) => {
        watch(source, callback, { deep: true, immediate: true })
    }

    /* -------------------------- 属性定义 -------------------------- */

    const setTimeOutList = []
    const pageLoading = reactive({
        loading: false,
        tip: undefined
    })
    const authInfo = localGet('app-user-store')
    const vid_z354kcjic1_imageUrl = 'http://10.40.0.33:9001/file-storage/493887559979984896.png'

    const vid_z354kcjic1_props = reactive({
        src: vid_z354kcjic1_imageUrl
    })
    const vid_crznpxme1j_imageUrl = 'http://10.40.0.33:9001/file-storage/493904223171733504.png'

    const vid_crznpxme1j_props = reactive({
        src: vid_crznpxme1j_imageUrl
    })

    // 处理校验
    const setSubFormName = (parentInfo, name) => {
        return [parentInfo.parents, parentInfo.cycleIndex, name]
    }

    /* ========================== 属性定义 ========================== */

    /* -------------------------- 元素数据引用 -------------------------- */

    /* ========================== 元素数据引用 ========================== */

    /* -------------------------- 页面数据 -------------------------- */

    /* ========================== 页面数据 ========================== */

    /* -------------------------- 响应 -------------------------- */

    /* ========================== 响应 ========================== */

    /* -------------------------- 函数 -------------------------- */

    /* ========================== 函数 ========================== */

    /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId
    })

    /* ========================== 页面参数 ========================== */

    /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================

    /* ========================== 组件事件处理方法 ========================== */

    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
    const queryUpdateFlag = ref(0)
    onMounted(() => {})

    onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
            repeat ? clearInterval(timer) : clearTimeout(timer)
        })
    })

    /* ========================== 生命周期 ========================== */

    /* -------------------------- 数据关联处理 -------------------------- */

    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */

    /* ========================== 数据关联处理 ========================== */

    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

    /* ========================== 不同组件自定义的处理逻辑 ========================== */

    // ================================定制化逻辑========================================
    import { nextTick } from 'vue'
    import * as echarts from 'echarts'
    // import chinaJson from './china'
    const chinaJson = {}
    const chartBox = ref(null)
    const loadingStatus = ref(false)
    const areaList = ref([
        // { itemName: '西南水泥', children: [{ itemName: '黑龙江省' }, { itemName: '云南省' }] },
    ])
    const proList = ref([
        // { itemName: '西南水泥', children: [{ itemName: '黑龙江省' }, { itemName: '云南省' }] },
    ])
    const dataId = ref('echarts-chinaMap')
    const proSelectIndex = ref(0)
    const areaSelIndex = ref(null)
    const typeSelectIndex = ref(0)
    const expends = ref({
        pro: true,
        area: true
    })
    const onExpends = type => {
        expends.value[type] = !expends.value[type]
        // if (type == 'pro') {
        //     proSelectIndex.value = null
        // }
        // if (type == 'area') {
        //     areaSelIndex.value = null
        // }
    }
    // 计算属性 mergeoptions
    const mergeoptions = computed(() => {
        const defaultOpt = {}
        return {
            ...defaultOpt,
            ...options.value
        }
    })

    const mainStyle = ref(document.body.offsetWidth)
    const proLineDatas = ref([])
    const typeList = ref([
        { itemName: '任务完成', type: 'TASK_DEVIATION' },
        { itemName: '资源投入', type: 'RESOURCE_DEVIATION' },
        { itemName: '成本统计', type: 'COST_DEVIATION' }
    ])
    const options = computed(() => ({
        // roam: true, // 开启鼠标缩放和平移漫游
        // zoom: 1, // 初始缩放比例
        // scaleLimit: { // 缩放的比例限制
        //     min: 1, // 最小缩放比例
        //     max: 20 // 最大缩放比例
        // },
        tooltip: {
            show: true,
            position: 'top',
            className: 'map-dialog',
            renderMode: 'html',
            formatter(params) {
                return params.data.factoryName
                // return `<div class="status-${params.data.legendsType}">${params.data.factoryName}<div class="value"><i></i>${params.data.deviation}</div></div>`
            }
        },
        grid: {
            top: 0,
            left: 0,
            right: 0,
            bottom: 0
        },
        geo: [
            {
                // top:530,
                map: 'chinaBoundary',
                // 避免边框选中，设置不响应事件
                silent: true,
                emphasis: {
                    disabled: true
                },
                itemStyle: {
                    normal: {
                        // borderWidth: 5,
                        areaColor: 'rgba(0, 0, 0, 0)',
                        borderColor: 'rgba(255, 255, 255, 0)'
                    }
                }
            }
        ],
        series: [
            {
                type: 'map',
                silent: true,
                selectedMode: false,
                map: 'china',
                coordinateSystem: 'geo',
                label: {
                    show: true,
                    color: '#333',
                    fontSize: 12
                },
                itemStyle: {
                    normal: {
                        areaColor: 'rgba(0, 0, 0, 0)',
                        borderColor: 'rgba(0, 0, 0, 0)',
                        borderJoin: 'round'
                    },
                    emphasis: {
                        label: {
                            show: true,
                            color: '#3a76ff',
                            fontSize: 12
                        },
                        borderWidth: 1.4,
                        borderJoin: 'round',
                        areaColor: 'rgba(56,177,255,.1)',
                        borderColor: '#3a76ff' // 设置省份分界线的颜色
                    }
                }
            },

            {
                type: 'effectScatter',
                coordinateSystem: 'geo',
                data: proLineDatas?.value.filter(item => !legendsDot.value[item.legendsType]) || [],
                // 标记点样式
                // symbolSize: 7,
                // symbolSize: item => {
                //     // 计算优先级
                //   if (newState.priority === '全部') {
                //     return 7; // 默认大小为 7
                //   }
                //     if (item.priority === newState.priority) {
                //         return 15 // 被选中优先级的大小
                //     } else {
                //         return 5 // 其他优先级的较小尺寸
                //     }
                // },
                symbolSize: function (val, params) {
                    if (newState.priority === '全部') {
                        return 7 // 默认大小为 7
                    }
                    // 检查是否存在符合当前优先级的数据
                    let hasMatchingData = false
                    for (let i = 0; i < proLineDatas.value.length; i++) {
                        if (proLineDatas.value[i].priority === newState.priority) {
                            hasMatchingData = true
                            break
                        }
                    }

                    if (!hasMatchingData) {
                        // 没有找到对应优先级的数据，给出提示
                        // 这里可以根据实际情况使用更合适的 message 提示方式，例如使用弹窗库
                        // 比如使用 element-ui 的 MessageBox
                        // this.$messagebox('提示', '无该优先级数据');
                        return 0 // 大小不变，使用默认大小
                    }

                    if (params.data.priority === newState.priority) {
                        return 7 // 被选中优先级的大小
                    } else {
                        return 0 // 其他优先级的较小尺寸
                    }
                    // if (params.data.priority === newState.priority) {
                    //     return 10 // 被选中优先级的大小
                    // } else {
                    //     return 5 // 其他优先级的较小尺寸
                    // }
                },
                showEffectOn: 'render'
            }
        ]
    }))

    //   初始化图表
    const initChartBox = () => {
        chartBox.value = echarts.init(document.getElementById('echarts-chinamap'), null, {
            renderer: 'svg',
            devicePixelRatio: 2
        })
        window.addEventListener('resize', () => {
            setMainStyle()
            chartBox.value?.resize()
        })
        renderChart()
        chartBox.value.on('click', bindMapClik)
    }

    //   绑定点击
    const bindMapClik = params => {
        if (params.componentType === 'series' && params.data) {
            const data = params.data
            getData(data, data.projectId, proList.value[proSelectIndex.value].itemName)
        }
    }

    //   渲染
    const renderChart = () => {
        if (!chartBox.value) {
            initChartBox()
            chartBox.value?.setOption(mergeoptions.value)
        } else {
            chartBox.value?.setOption(mergeoptions.value)
        }
    }

    // 切换分类
    const onChangeType = index => {
        if (index === typeSelectIndex.value) return
        typeSelectIndex.value = index
        proSelectIndex.value = 0
        onGetProDatas()
    }
    //切换产线
    const onChangeProLines = (index, type) => {
        if (index > 0 && typeSelectIndex.value === 1) {
            return
        }
        proSelectIndex.value = index
        areaSelIndex.value = null
        expends.value.pro = true
        onGetProDatas()
    }

    // 切换区域
    const onChangeArea = index => {
        expends.value.area = true
        toogleHighlight('downplay', areaSelIndex.value || 0)
        nextTick(() => {
            areaSelIndex.value = index
            toogleHighlight('highlight', index)
        })
    }

    // 切换区域
    const legendsDot = ref([false, false, false])
    const onChangelegends = index => {
        legendsDot.value[index] = !legendsDot.value[index]
        renderChart()
    }

    //   切换区域
    const toogleHighlight = (type = 'highlight', index) => {
        const area = areaList.value[index]
        area.children.forEach(item => {
            const name = item.itemName.replace(/[省市自治区]/g, '')
            chartBox.value?.dispatchAction({
                type,
                name: name
            })
        })
    }

    //
    const ongetoperation = params => {
        loadingStatus.value = true
        post('/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/search', params)
            .then(res => {
                const colors = ['#52c41a', '#ffc500', '#f5222d']
                const colors1 = ['#52c41a', '#f5222d']
                proLineDatas.value =
                    res.data?.map(item => {
                        const index = Number(item.deviation) < 21 ? 0 : Number(item.deviation) > 50 ? 2 : 1
                        const index1 = Number(item.deviation) > 0 ? 1 : 0
                        // 这俩测试用
                        const randomCost = Math.floor(Math.random() * 3)
                        // 这俩测试用
                        return {
                            ...item,
                            value: [item.longuide, item.latitude],
                            itemStyle: {
                                // color: colors[index]
                                color: typeSelectIndex.value === 2 ? colors1[index1] : colors[index]
                            },
                            rippleEffect: {
                                brushType: 'fill',
                                scale: 3,
                                number: 2,
                                period: 3,
                                // color: colors[index]
                                color: typeSelectIndex.value === 2 ? colors1[index1] : colors[index]
                            },
                            legendsType: index,
                            // 下面俩测试使用
                            cost: randomCost
                            // 测试使用
                        }
                    }) || []
                renderChart()
                loadingStatus.value = false
            })
            .catch(error => {
                console.error('失败:', error)
            })
    }

    const onGetProDatas = () => {
        ongetoperation({
            productLine: proList.value[proSelectIndex.value].itemName,
            type: typeList.value[typeSelectIndex.value].type
        })
    }

    const onGetChinaJson = async params => {
        if (sessionStorage.getItem('chinaMapJson')) {
            return JSON.parse(sessionStorage.getItem('chinaMapJson'))
        }
        const res = await get('/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/china')
        sessionStorage.setItem('chinaMapJson', res.data)
        return JSON.parse(res.data)
    }

    const onAreaList = params => {
        if (sessionStorage.getItem('onAreaList')) {
            return JSON.parse(sessionStorage.getItem('onAreaList'))
        }
        get(' /solution-ppm-basic-data/api/v1/dictionary/search_tree/OPERATION.AREA')
            .then(res => {
                areaList.value = res.data || []
                sessionStorage.setItem('areaList', JSON.stringify(res.data))
            })
            .catch(error => {
                console.error('失败:', error)
            })
    }

    const getProList = params => {
        get(' /solution-ppm-basic-data/api/v1/dictionary/search/OPERATION.PRODUCT_LINE')
            .then(res => {
                proList.value = res.data || []
                if (res.data && res.data[0]) {
                    onChangeProLines(0)
                }
            })
            .catch(error => {
                console.error('失败:', error)
            })
    }

    const init = async () => {
        setMainStyle()
        const chinaJsonData = (await onGetChinaJson()) || chinaJson
        echarts.registerMap('china', chinaJsonData)
        echarts.registerMap('chinaBoundary', chinaJsonData)
        initChartBox()
        onAreaList()
        getProList()
    }

    onMounted(() => {
        init()
    })
    const setMainStyle = () => {
        const dom = document.getElementById('mainContent')
        let cliWidth = dom.offsetWidth
        let cliHeight = dom.offsetHeight
        let contW = 1126
        let contH = 851
        let w = cliWidth / contW
        let h = cliHeight / contH
        let per = w < h ? w : h
        mainStyle.value = `transform: scale(${per * 1.15} , ${per * 1.15 * 0.89});transform-origin:center;margin-top:${
            (contH * (per - 1)) / 2
        }px;`
    }

    onBeforeUnmount(() => {
        if (chartBox.value) {
            chartBox.value.dispose()
            chartBox.value = null
            window.removeEventListener('resize', () => {
                chartBox.value?.resize()
            })
        }
    })

    const watchMergeOptions = watch(
        mergeoptions,
        () => {
            renderChart()
        },
        { deep: true }
    )

    // 暴露给模板的变量和函数
    defineExpose({
        areaList,
        areaSelIndex,
        onChangeArea,
        toogleHighlight
    })
    // 原里程碑进度部分
    const filteredColumns = computed(() => {
        return columnState.columns
            .map(column => {
                const updatedColumn = {
                    ...column,
                    children:
                        column.children && Array.isArray(column.children)
                            ? column.children.filter(child => child.visible)
                            : []
                }

                if (updatedColumn.children.length === 0 && column.children?.length > 0) {
                    updatedColumn.visible = false
                }

                return updatedColumn.visible === false ? null : updatedColumn
            })
            .filter(Boolean)
    })
    const overStyle = ref({
        maxWidth: '300px',
        fontSize: '16px'
    })
    const customOkCellStyle = () => {
        return {
            style: {
                padding: '4px 16px'
            }
        }
    }
    const handleResizeColumn = (w, col) => {
        const width = w - 50 // 确保宽度被计算并且减去额外空间

        // 根据列标题来确定不同的 div
        let div = null
        if (col.title === '进展') {
            div = document.querySelectorAll('.omit-div')
        } else if (col.title.includes('问题&风险')) {
            div = document.querySelectorAll('.omit-div-question')
        } else if (col.title === '生产计划') {
            div = document.querySelectorAll('.omit-div-productionPlan')
        } else if (col.title === '客情关系') {
            div = document.querySelectorAll('.omit-div-customerRelationship')
        }

        // 如果找到了对应的 div，更新其宽度
        if (div.length > 0) {
            div.forEach(item => {
                item.style.width = `${width}px`
            })
            overStyle.value.maxWidth = `${width}px` // 更新 tooltip 最大宽度
        }

        // 更新 columnState 中的列宽
        columnState.columns = columnState.columns.map(item => {
            if (item.dataIndex === col.dataIndex) {
                return { ...item, width: w } // 更新该列的宽度
            }
            return item
        })

        // 如果列有子列，确保子列也能根据父列的宽度进行更新
        if (col.children) {
            col.children.forEach(child => {
                columnState.columns = columnState.columns.map(item => {
                    if (item.dataIndex === child.dataIndex) {
                        return { ...item, width: w } // 更新子列的宽度
                    }
                    return item
                })
            })
        }
    }
    function getLcbData(id, type, areaName) {
        if (type !== '水泥配料') {
            return
        }
        ftfState.filter.projectId = id
        ftfState.tableLoading = true
        post('/solution-ppm/api/v2/built-in-system-ppm/project_progress/search ', {
            ...ftfState.filter,
            areaName: !id ? [areaName] : null,
            customSort: ftfState.filter.customSort
        })
            .then(data => {
                if (data.code !== 200) {
                    ftfState.dataSource = []
                    message.error(data.message)
                    return
                }

                ftfState.dataSource = data.data.map(({ customDataMap, ...rest }) => ({
                    ...rest,
                    ...customDataMap // 解构并展开 customDataMap 的内容
                }))
                ftfState.modalVisible = true
            })
            .finally(() => {
                ftfState.tableLoading = false
            })
    }
    const columnState = reactive({
        columns: [
            {
                title: '序号',
                dataIndex: 'count',
                align: 'center',
                width: 50,
                fixed: 'left',
                ellipsis: true
            },
            {
                'title': '区域',
                'dataIndex': 'areaName',
                ellipsis: true,
                width: 120,
                fixed: 'left',
                align: 'center'
            },
            {
                title: '工厂名称',
                dataIndex: 'projectShortName',
                ellipsis: true,
                width: 130,
                fixed: 'left',
                align: 'center'
            },

            {
                title: '批次',
                dataIndex: 'batch',
                ellipsis: true,
                width: 80,
                align: 'center',
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },

            {
                title: '产品类型',
                dataIndex: 'productType',
                ellipsis: true,
                width: 80,
                align: 'center',
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '项目总监',
                dataIndex: 'projectDirector',
                ellipsis: true,
                align: 'center',
                width: 80,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '水泥专家',
                dataIndex: 'businessExpert',
                align: 'center',
                ellipsis: true,
                width: 80,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '项目经理',
                dataIndex: 'pmName',
                align: 'center',
                ellipsis: true,
                width: 80,
                customCell: customOkCellStyle,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '熟料算法',
                dataIndex: 'clinkerAlgorithmExpert',
                align: 'center',
                ellipsis: true,
                width: 80,
                customCell: customOkCellStyle,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '水泥算法',
                dataIndex: 'cementAlgorithmExpert',
                align: 'center',
                ellipsis: true,
                width: 80,
                customCell: customOkCellStyle,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '商务',
                dataIndex: 'preSaleManager',
                align: 'center',
                ellipsis: true,
                width: 80,
                customCell: customOkCellStyle,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },

            {
                title: '数据积累',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'collectionMappingPlanStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingPlanStartTime)
                            const timeB = dayjs(b.collectionMappingPlanStartTime)

                            // 处理空值，确保空值排在最后
                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                            if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                            // 有效的时间做正常排序
                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '计划结束',
                        dataIndex: 'collectionMappingPlanEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingPlanEndTime)
                            const timeB = dayjs(b.collectionMappingPlanEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'collectionMappingActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingActualStartTime)
                            const timeB = dayjs(b.collectionMappingActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '实际结束',
                        dataIndex: 'collectionMappingActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingActualEndTime)
                            const timeB = dayjs(b.collectionMappingActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'collectionMappingExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingExpectStartTime)
                            const timeB = dayjs(b.collectionMappingExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'collectionMappingExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.collectionMappingExpectEndTime)
                            const timeB = dayjs(b.collectionMappingExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },

            {
                title: '自学习表数据确认',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'processingTableConfirmPlanStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmPlanStartTime)
                            const timeB = dayjs(b.processingTableConfirmPlanStartTime)

                            // 处理空值，确保空值排在最后
                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                            if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                            // 有效的时间做正常排序
                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '计划结束',
                        dataIndex: 'processingTableConfirmPlanEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmPlanEndTime)
                            const timeB = dayjs(b.processingTableConfirmPlanEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'processingTableConfirmActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmActualStartTime)
                            const timeB = dayjs(b.processingTableConfirmActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '实际结束',
                        dataIndex: 'processingTableConfirmActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmActualEndTime)
                            const timeB = dayjs(b.processingTableConfirmActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'processingTableConfirmExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmExpectStartTime)
                            const timeB = dayjs(b.processingTableConfirmExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'processingTableConfirmExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.processingTableConfirmExpectEndTime)
                            const timeB = dayjs(b.processingTableConfirmExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },
            {
                title: '数据建模',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'modelStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelStartTime)
                            const timeB = dayjs(b.modelStartTime)

                            // 处理空值，确保空值排在最后
                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                            if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                            // 有效的时间做正常排序
                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '计划结束',
                        dataIndex: 'modelEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelEndTime)
                            const timeB = dayjs(b.modelEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'modelActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelActualStartTime)
                            const timeB = dayjs(b.modelActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '实际结束',
                        dataIndex: 'modelActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelActualEndTime)
                            const timeB = dayjs(b.modelActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'modelExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelExpectStartTime)
                            const timeB = dayjs(b.modelExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'modelExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.modelExpectEndTime)
                            const timeB = dayjs(b.modelExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },
            {
                title: '试运行',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'testRunStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunStartTime)
                            const timeB = dayjs(b.testRunStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '计划结束',
                        dataIndex: 'testRunEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunEndTime)
                            const timeB = dayjs(b.testRunEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'testRunActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunActualStartTime)
                            const timeB = dayjs(b.testRunActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际结束',
                        dataIndex: 'testRunActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunActualEndTime)
                            const timeB = dayjs(b.testRunActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'testRunExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunExpectStartTime)
                            const timeB = dayjs(b.testRunExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'testRunExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.testRunExpectEndTime)
                            const timeB = dayjs(b.testRunExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },
            {
                title: '正式运行',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'runStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runStartTime)
                            const timeB = dayjs(b.runStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '计划结束',
                        dataIndex: 'runEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runEndTime)
                            const timeB = dayjs(b.runEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'runActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runActualStartTime)
                            const timeB = dayjs(b.runActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际结束',
                        dataIndex: 'runActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runActualEndTime)
                            const timeB = dayjs(b.runActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'runExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runExpectStartTime)
                            const timeB = dayjs(b.runExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'runExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.runExpectEndTime)
                            const timeB = dayjs(b.runExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },
            {
                title: '验证',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'verifyStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyStartTime)
                            const timeB = dayjs(b.verifyStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '计划结束',
                        dataIndex: 'verifyEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyEndTime)
                            const timeB = dayjs(b.verifyEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'verifyActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyActualStartTime)
                            const timeB = dayjs(b.verifyActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际结束',
                        dataIndex: 'verifyActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyActualEndTime)
                            const timeB = dayjs(b.verifyActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'verifyExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyExpectStartTime)
                            const timeB = dayjs(b.verifyExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'verifyExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.verifyExpectEndTime)
                            const timeB = dayjs(b.verifyExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },
            {
                title: '验收',
                ellipsis: true,
                align: 'center',
                visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                children: [
                    {
                        title: '计划开始',
                        dataIndex: 'checkStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkStartTime)
                            const timeB = dayjs(b.checkStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },

                    {
                        title: '计划结束',
                        dataIndex: 'checkEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkEndTime)
                            const timeB = dayjs(b.checkEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际开始',
                        dataIndex: 'checkActualStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkActualStartTime)
                            const timeB = dayjs(b.checkActualStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '实际结束',
                        dataIndex: 'checkActualEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkActualEndTime)
                            const timeB = dayjs(b.checkActualEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计开始',
                        dataIndex: 'checkExpectStartTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkExpectStartTime)
                            const timeB = dayjs(b.checkExpectStartTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    },
                    {
                        title: '预计结束',
                        dataIndex: 'checkExpectEndTime',
                        ellipsis: true,
                        align: 'center',
                        width: 150,
                        sorter: (a, b) => {
                            const timeA = dayjs(a.checkExpectEndTime)
                            const timeB = dayjs(b.checkExpectEndTime)

                            if (!timeA.isValid() && !timeB.isValid()) return 0
                            if (!timeA.isValid()) return 1
                            if (!timeB.isValid()) return -1

                            return timeA - timeB
                        },
                        visible: true
                    }
                ]
            },

            {
                title: '项目阶段',
                dataIndex: 'milepostName',
                sorter: true,
                ellipsis: true,
                align: 'center',
                width: 80,
                sorter: true,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '项目状态',
                dataIndex: 'projectStatus',
                ellipsis: true,
                align: 'center',
                width: 80,
                visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
            },
            {
                title: '进展',
                dataIndex: 'progress',
                ellipsis: true,
                resizable: true,
                align: 'center',
                width: 350,
                minWidth: 350,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },

            {
                title: '问题&风险',
                dataIndex: 'question',
                ellipsis: true,
                align: 'center',
                resizable: true,
                width: 350,
                minWidth: 350,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '风险等级',
                dataIndex: 'riskLevel',
                align: 'center',
                ellipsis: true,
                width: 120,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '项目支持',
                dataIndex: 'supportors',
                align: 'center',
                ellipsis: true,
                width: 120,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '正式运行持续天数',
                dataIndex: 'runDays',
                align: 'center',
                ellipsis: true,
                width: 120,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '综合样20次',
                dataIndex: 'comprehensiveSample',
                align: 'center',
                ellipsis: true,
                width: 120,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '降本空间',
                dataIndex: 'expectedCostReduction',
                align: 'center',
                ellipsis: true,
                width: 120,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '生产计划',
                dataIndex: 'productionPlan',
                resizable: true,
                align: 'center',
                ellipsis: true,
                width: 350,
                minWidth: 350,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            },
            {
                title: '客情关系',
                dataIndex: 'customerRelationship',
                resizable: true,
                align: 'center',
                ellipsis: true,
                width: 350,
                minWidth: 350,
                visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
            }
            // 其他通用列
        ],
        newColumns: [
            {
                title: '',
                dataIndex: 'name',
                align: 'center',
                fixed: 'left',
                ellipsis: true
            },

            {
                title: '数据积累',
                ellipsis: true,
                dataIndex: 'dataCollector',
                align: 'center'
            },

            {
                title: '自学习表数据确认',
                width: 150,
                ellipsis: true,
                dataIndex: 'selfLearnConfirm',
                align: 'center'
            },
            {
                title: '数据建模',
                ellipsis: true,
                dataIndex: 'modeling',
                align: 'center'
            },
            {
                title: '试运行',
                ellipsis: true,
                dataIndex: 'testRun',
                align: 'center'
            },
            {
                title: '正式运行',
                ellipsis: true,
                dataIndex: 'run',
                align: 'center'
            },
            {
                title: '验证',
                ellipsis: true,
                dataIndex: 'verify',
                align: 'center'
            },
            {
                title: '验收',
                dataIndex: 'check',
                ellipsis: true,
                align: 'center'
            }
        ]
    })
    const ftfState = reactive({
        detailVisible: false,
        modalVisible: false,
        radioValue: '全部',
        dataSource: [],
        tableLoading: false,
        filter: {
            areaName: undefined,
            projectDirector: undefined,
            projectId: undefined,
            batch: undefined,
            milepostName: undefined,
            riskLevel: [],
            projectStatus: undefined,
            customSort: {
                'sortDirection': 'ASC',
                'filed': 'AREA'
            }
            // milepostOrder: false
        },
        checkList: ['计划开始', '计划结束', '实际开始', '实际结束', '预计开始', '预计结束'],
        baseCheckList: ['批次', '产品类型', '项目总监', '水泥专家', '项目经理', '算法', '商务', '项目阶段', '项目状态'],
        milepostCheckList: [],
        // milepostCheckList: ['验收', '验证', '正式运行', '试运行', '数据建模', '自学习表数据确认', '数据积累'],
        otherCheckList: [
            '进展',
            '问题风险',
            '风险等级',
            '项目支持',
            '正式运行持续天数',
            '综合样20次',
            '降本空间',
            '生产计划',
            '客情关系'
        ],
        settingVisible: false,
        activeKey: '基础信息'
    })
    const handleTableChange = (pagination, filters, sorter) => {
        let currentSortDirection = 'ASC' // 默认排序方向为 ASC
        let currentField = 'AREA' // 默认字段为 AREA

        if (sorter.column && sorter.column.dataIndex === 'milepostName') {
            // 判断排序方向
            if (sorter.order === 'ascend') {
                currentSortDirection = 'ASC'
            } else if (sorter.order === 'descend') {
                currentSortDirection = 'DESC'
            }
            // 设置自定义排序
            ftfState.filter.customSort = {
                sortDirection: currentSortDirection,
                filed: 'MILEPOST' // 根据需要修改字段名
            }
        } else {
            // 如果没有对 'milepostName' 进行排序，使用默认排序
            ftfState.filter.customSort = {
                sortDirection: currentSortDirection,
                filed: currentField
            }
        }
        getLcbData()
    }
    // 原里程碑进度部分
    const apiMap = {
        '任务完成': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/task_search',
        '资源投入': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/resource_search',
        '成本统计': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/cost_search'
    }
    function getData(item, id, type, areaName) {
        if (type !== '水泥配料') {
            return
        }
        ftfState.filter.projectId = id
        ftfState.tableLoading = true
        post(apiMap[typeList.value[typeSelectIndex.value].itemName], {
            productLine: proList.value[proSelectIndex.value].itemName,
            type: typeList.value[typeSelectIndex.value].type,
            projectId: id
        })
            .then(data => {
                if (data.code !== 200) {
                    ftfState.dataSource = {}
                    message.error(data.message)
                    return
                }
                let dataNew = {
                    ...data.data,
                    rippleEffect: item.rippleEffect,
                    deviation: item.deviation
                }
                ftfState.dataSource = dataNew
                ftfState.detailVisible = true
            })
            .finally(() => {
                ftfState.tableLoading = false
            })
    }
    // 里程碑进度表弹窗
    const newState = reactive({
        priority: '全部'
    })
    function changeSymbelSize() {
        // ongetoperation({
        //     productLine: proList.value[proSelectIndex.value].itemName,
        //     type: typeList.value[typeSelectIndex.value].type
        // })
        renderChart()
    }
    function getOverExpenditure(totalPeriodDeviation) {
        if (totalPeriodDeviation == 0) {
            return '未超支'
        } else if (totalPeriodDeviation > 0) {
            return `超支${totalPeriodDeviation}%`
        } else if (totalPeriodDeviation < 0) {
            return '未超支'
        }
    }
    function getCostColor(item, flag) {
        console.log(item)
        if (item === null || item === undefined) {
            return {
                color: flag ? '#595959' : '#262626'
            }
        } else if (item > 0) {
            return {
                color: '#F5222D'
            }
        } else if (item <= 0) {
            return {
                color: '#52C41A'
            }
        }
    }
    function getTotalCostColor(item, flag) {
        if (item === null || item === undefined) {
            return {
                color: flag ? '#595959' : '#262626'
            }
        } else if (item > 0) {
            return {
                color: '#F5222D'
            }
        } else if (item <= 0) {
            return {
                color: '#52C41A'
            }
        }
    }
    function getCostDiffer() {
        if (ftfState.dataSource.costDeviation === 0) {
            return '未超支'
        }
        if (ftfState.dataSource.costDeviation > 0) {
            return `超支${ftfState.dataSource.costDeviation}%`
        } else if (ftfState.dataSource.costDeviation < 0) {
            return '未超支'
        }
    }
    function getTaskStatus(data) {
        if (data === 0 || data < 0) {
            return '未超期'
        } else if (data > 0) {
            return `延期${data}%`
        } else if (!data) {
            return '--'
        }
    }
    function getTotalTaskStatus(data) {
        if (data === 0 || data < 0) {
            return '未超期'
        } else if (data > 0) {
            return `延期${data}%`
        } else if (!data) {
            return '--'
        }
    }

    //     成本基准
    function getReferenceColor(item, flag) {
        if (item === null || item === undefined) {
            return {
                color: flag ? '#595959' : '#262626'
            }
        } else if (item > 0) {
            return {
                color: '#F5222D'
            }
        } else if (item <= 0) {
            return {
                color: '#52C41A'
            }
        }
    }
    // 累计周期偏差
    function getTotalReferenceColor(item, flag) {
        if (item === null || item === undefined) {
            return {
                color: flag ? '#595959' : '#262626'
            }
        } else if (item > 0) {
            return {
                color: '#F5222D'
            }
        } else if (item <= 0) {
            return {
                color: '#52C41A'
            }
        }
    }
    // 新-模板项目审核标准格式
    function handlerGetSpace(data) {
        return data?.split(/[;；]/)
    }
    function getNameColor(num, flag) {
        if (num === null || num === undefined) {
            return
        }
        const colors = ['#52c41a', '#ffc500', '#f5222d']
        const index = num < 21 ? 0 : num > 50 ? 2 : 1
        return {
            color: colors[index]
        }
    }
</script>
<style lang="less" scoped>
    .page_root {
        width: 100%;
        height: 100%;
        overflow: auto;
    }
    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container) {
        height: 100%;
    }
    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }
    .page_root :deep(.@{ant-prefix}-table) {
        flex: auto;
        overflow: auto;
    }
    .table-moreBtn_down {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100px;
    }

    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
        background: #ebf1ff;
    }

    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
        z-index: 1;
    }
    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 15px !important;
        width: calc(100% - 15px);
    }
    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 30px !important;
        width: calc(100% - 30px);
    }
    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 45px !important;
        width: calc(100% - 45px);
    }
    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 60px !important;
        width: calc(100% - 60px);
    }

    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list) {
        height: 100%;
        width: 50%;
    }

    .img {
        display: inline-block;
        background-size: 100%;
        background-repeat: no-repeat;
    }
    .icon-green {
        background: url('http://10.40.0.33:9001/file-storage/490835387857987584.svg');
    }
    .icon-yellow {
        background: url('http://10.40.0.33:9001/file-storage/490835387736352768.svg');
    }
    .icon-red {
        background: url('http://10.40.0.33:9001/file-storage/490835387811850240.svg');
    }
    .icon-data-sel {
        background: url('http://10.40.0.33:9001/file-storage/490835387876861952.svg');
    }
    .icon-data {
        background: url('http://10.40.0.33:9001/file-storage/490835387765712896.svg');
    }
    .icon-pro {
        background: url('http://10.40.0.33:9001/file-storage/490835387717478400.svg');
    }
    .icon-pro-sel {
        background: url('http://10.40.0.33:9001/file-storage/490835387895736320.svg');
    }
    .icon-area {
        background: url('http://10.40.0.33:9001/file-storage/490835385127495680.svg');
    }
    .icon-area-sel {
        background: url('http://10.40.0.33:9001/file-storage/490835387782490112.svg');
    }
    .icon-more {
        background: url('http://10.40.0.33:9001/file-storage/490791204612958208-source.svg');
    }
    .icon-more-sel {
        background: url('http://10.40.0.33:9001/file-storage/491018405316880384-source.svg');
    }
    ul,
    li {
        padding: 0;
        margin: 0;
    }
    .top-title {
        height: 64px;
        background: url('http://10.40.0.33:9001/file-storage/490835387830724608.svg');
        background-size: contain;
        background-position: center;
        background-repeat: no-repeat;
        display: flex;
        justify-content: center;
        align-items: center;
        font-family: PingFangSC-Semibold;
        font-size: 36px;
        color: #ffffff;
        letter-spacing: 10px;
        font-weight: 600;
    }
    .left-geo {
        position: absolute;
        cursor: pointer;
        z-index: 999;
        top: -24px;
        left: 16px;
        bottom: 24px;
        display: flex;
        flex-direction: column;
        li {
            line-height: 100%;
        }
        .proAreaSels {
            background-image: linear-gradient(179deg, rgba(218, 237, 255, 0.4) 0%, rgba(242, 253, 255, 0.4) 100%);
            box-shadow: 0 2px 10px 0 #d5e7ed;
            border-radius: 4px;
            border: 1px solid;
            border-image: linear-gradient(to bottom, #3875ff, #fff, #fff, #3875ff) 1;
            padding: 16px;
            max-width: 240px;
            min-width: 200px;
            width: 12vw;
            box-sizing: border-box;
            margin-top: 16px;
            flex: 1;
            .icon.img {
                width: 16px;
                height: 16px;
            }

            .unexpend {
                li {
                    display: none;
                }
                .arrow-right {
                    transform: rotate(90deg);
                }
            }
            .show-active {
                display: none;
            }
            .active {
                .arrow-right {
                    border-left: 8px solid #3875ff;
                }
                .show-active {
                    display: unset;
                }
                .hide-active {
                    display: none;
                }
            }
            .name {
                border-radius: 2px;
                height: 32px;
                display: flex;
                align-items: center;
                padding: 0 9px;
                font-family: PingFangSC-Semibold;
                font-size: 16px;
                letter-spacing: 0;
                line-height: 32px;
                font-weight: 600;
                &.active {
                    background: rgba(56, 117, 255, 0.1);
                    color: #3875ff;
                    .arrow-right {
                        border-left: 8px solid #3875ff;
                    }
                }
            }
            .icon {
                margin-right: 4px;
            }
            .arrow-right {
                display: inline-block;
                border-left: 8px solid #8c8c8c;
                border-top: 6px solid transparent;
                border-bottom: 6px solid transparent;
                transform: rotate(0deg);
            }
            li {
                display: flex;
                line-height: 32px;
                align-items: center;
                padding-left: 39px;
                font-family: PingFangSC-Regular;
                font-size: 14px;
                color: #595959;
                letter-spacing: 0;
                line-height: 32px;
                font-weight: 400;
                &.active {
                    background: rgba(56, 117, 255, 0.1);
                    color: #3875ff;
                }
                &.disabled {
                    font-family: PingFangSC-Regular;
                    font-size: 14px;
                    color: #acacac;
                    letter-spacing: 0;
                    line-height: 32px;
                    font-weight: 400;
                    cursor: not-allowed;
                }
            }
        }
        .typeSels {
            position: relative;
            background: #ffffff;
            border: 1px solid #3875ff;
            border-radius: 4px;
            font-size: 14px;
            color: #262626;
            letter-spacing: 0;
            text-align: center;
            line-height: 20px;
            font-weight: 400;
            display: inline-flex;
            width: 267px;
            li {
                flex: 1;
                display: inline-block;
                padding: 6px 16px;
                line-height: 20px;
                white-space: nowrap;
                &.action {
                    background: #3875ff;
                    color: #fff;
                }
            }
            li:nth-child(-n + 2) {
                border-right: 1px solid #3875ff;
            }
            .priority-div {
                position: absolute;
                right: -176px;
                :deep(.ant3-select:not(.ant3-select-customize-input) .ant3-select-selector) {
                    border-color: #3875ff;
                    color: #3875ff;
                    text-align: left;
                }
                :deep(.ant3-select-arrow) {
                    color: #3875ff;
                }
            }
        }
    }
    .main-content {
        width: 100%;
        height: 100%;
        overflow: hidden;
        position: relative;
        background-color: #fff;
        //border: 1px solid blue;
        background: url('http://10.40.0.33:9001/file-storage/490835387925096448.svg');
        background-size: cover;
        background-repeat: no-repeat;
        background-position: center;
        * {
            user-select: none;
            -webkit-user-select: none; /* Safari */
            -moz-user-select: none; /* Firefox */
            -ms-user-select: none; /* IE 10 and IE 11 */
        }
    }
    .content {
        padding: 0 16px;
        display: flex;
        justify-content: center;
        position: relative;
    }
    .echarts-content {
        margin-left: 7%;
        //border: 1px solid red;
        width: 1126px;
        height: 794px;
        position: relative;
        //border: 1px solid red;
        overflow: hidden;
        //transform: scale(1, 0.96);
        //transform: scale(1, 0.87);
        transform-origin: 0 0;
        .china-map-bg {
            position: absolute;
            top: 40px;
            left: 112px;
            width: 898px;
            height: 634px;
            transform: scale(1, 1.152);
            transform-origin: top;
            background: url('http://10.40.0.33:9001/file-storage/490835387677632512.svg');
            background-size: cover;
        }
    }
    .legend {
        position: absolute;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        margin-top: 16px;
        z-index: 9;
        li {
            display: flex;
            align-items: center;
            margin: 0 12px;
            cursor: pointer;
            &.gray {
                opacity: 0.56;
            }
            .icon {
                width: 24px;
                height: 24px;
                margin-right: 8px;
            }
        }
    }
    .echarts-main {
        width: 1126px;
        height: 2000px;
        position: relative;
        transform: translateY(-472px);
    }
    .fill {
        color: red;
    }

    ::v-deep .map-dialog {
        background: #ffffff;
        border: 1px solid #3875ff !important;
        box-shadow: 0 4px 0 0 rgba(56, 117, 255, 0.64) !important;
        border-radius: 2px 2px 2px 0 0 0 2px !important;
        font-family: PingFangSC-Regular;
        font-size: 14px !important;
        color: #262626 !important;
        letter-spacing: 0 !important;
        text-align: center !important;
        font-weight: 400 !important;

        .value {
            font-size: 10px;
        }
        .status-0 {
            .value {
                color: #52c41a;
            }
        }
        .status-1 {
            .value {
                color: #ff8c00;
            }
        }
        .status-2 {
            .value {
                color: #f5222d;
            }
        }
    }

    ::v-deep .map-dialog::after,
    ::v-deep .map-dialog::before {
        content: '';
        position: absolute;
        bottom: -10px; /* 箭头的顶部位置，负数表示向上移动 */
        left: 50%; /* 箭头的水平中心位置 */
        margin-left: -10px; /* 将箭头水平居中对齐 */
        width: 0;
        height: 0;
        border-left: 10px solid transparent; /* 左边框透明 */
        border-right: 10px solid transparent; /* 右边框透明 */
        border-top: 10px solid #fff; /* 底边框设置箭头颜色和大小 */
    }

    ::v-deep .map-dialog::before {
        margin-left: -16px; /* 将箭头水平居中对齐 */
        bottom: -16px; /* 箭头的顶部位置，负数表示向上移动 */
        border-left: 16px solid transparent; /* 左边框透明 */
        border-right: 16px solid transparent; /* 右边框透明 */
        border-top: 16px solid rgba(56, 117, 255, 0.64); /* 底边框设置箭头颜色和大小 */
    }

    /*
  里程碑进度表样式
  */
    /*冯腾飞样式*/
    .kb-table-box:deep(.@{ant-prefix}-table-thead) > tr > th {
        background: #3875ff;
        color: #fff;
        font-weight: 600;
        padding: 8px 16px;
        border-right: 1px solid #d9d9d9 !important;
        position: relative;
    }
    .kb-table-box :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-family: arial, helvetica, 'microsoft yahei';
        font-weight: 400;
        color: #262626;
        border-bottom: 1px solid #d9d9d9;
        padding: 8px 16px;
        word-break: break-all;
    }
    .search-radio {
        margin-bottom: 16px;
    }
    .db-click-name {
        width: 120px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        height: 30px;
        line-height: 30px;
    }
    .omit-div,
    .omit-div-question,
    .omit-div-productionPlan,
    .omit-div-customerRelationship {
        width: 320px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        height: 100%;
        padding: 0 8px;
    }
    .plus-icon {
        position: absolute;
        right: 0;
        top: 0;
        cursor: pointer;
    }
    .progress-click {
        height: 30px;
        line-height: 30px;
        cursor: pointer;
        display: flex;
    }
    :deep(.ant3-modal-header) {
        padding: 0;
        border: none;
    }
    .modal-body {
        height: 800px;
        overflow-y: auto;
        background-image: url('http://10.40.0.33:9001/file-storage/493887559979984896-source.png');
        background-size: cover;
        padding: 32px;
        padding-bottom: 0;
    }
    .modal-top {
        display: flex;
        gap: 24px;
        margin-bottom: 24px;
        .modal-top-left {
            height: 138px;
            background: rgba(255, 255, 255, 0.75);
            border: 2px solid #ffffff;
            border-radius: 4px;
            padding: 16px 24px;

            .left-top {
                display: flex;
                margin-bottom: 4px;
                .left-top-img {
                    background-size: cover;
                    height: 20px;
                    width: 20px;
                    background-image: url('http://10.40.0.33:9001/file-storage/493888275024930816-source.png');
                }
                .left-top-msg {
                    font-size: 16px;
                    color: #262626;
                    letter-spacing: 0;
                    font-weight: 500;
                }
            }
            .left-bottom {
                display: flex;
                flex-direction: row;
                gap: 48px;
                .bottom-left {
                    width: 50%;
                    display: flex;
                    gap: 4px;
                    flex-direction: column;
                    .bottom-left-item {
                        display: flex;
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
                .bottom-right {
                    position: relative;
                    flex: 1;
                    display: flex;
                    gap: 4px;
                    flex-direction: column;
                    .route {
                        background-size: cover;
                        height: 76px;
                        width: 1px;
                        background-image: url('http://10.40.0.33:9001/file-storage/493904223171733504-source.png');
                        position: absolute;
                        top: 58%;
                        left: -24px;
                        transform: translate(-50%, -50%);
                    }
                    .bottom-right-item {
                        display: flex;
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
                .normal {
                    color: #262626;
                }
                .exceed {
                    color: #f5222d;
                }
            }
        }
        .modal-top-right {
            width: 260px;
            height: 138px;
            background: rgba(255, 255, 255, 0.75);
            border: 2px solid #ffffff;
            border-radius: 4px;
            padding: 16px 24px;
            .right-top {
                gap: 8px;
                display: flex;
                margin-bottom: 4px;
                align-items: center;
                .right-top-img {
                    background-size: cover;
                    height: 20px;
                    width: 20px;
                    background-image: url('http://10.40.0.33:9001/file-storage/493888385750362112-source.png');
                }
                .right-top-msg {
                    font-size: 16px;
                    color: #262626;
                    letter-spacing: 0;
                    font-weight: 500;
                }
            }
            .right-bottom {
                display: flex;
                flex-direction: column;
                gap: 4px;
                .bottom-right-item {
                    display: flex;
                    .title {
                        font-size: 14px;
                        color: #595959;
                        letter-spacing: 0;
                        font-weight: 400;
                        white-space: nowrap;
                    }
                    .msg {
                        font-size: 14px;
                        color: #262626;
                        letter-spacing: 0;
                        font-weight: 500;
                        white-space: nowrap;
                    }
                }
            }
        }
    }
    .kb-table-box {
        background: rgba(255, 255, 255, 0.75);
        border: 2px solid #ffffff;
        border-radius: 4px;
        padding: 16px 24px;
        .inner-table {
            background: rgba(255, 255, 255, 0.5);
            border: 1px solid #3875ff;
            border-radius: 4px;
            padding: 16px 24px;
            .inner-top-main {
                margin-bottom: 4px;
                display: flex;
                .inner-top-item {
                    display: flex;
                    flex-direction: column;
                    gap: 8px;
                    flex-grow: 1;
                    .item-son {
                        display: flex;
                        justify-content: flex-start;
                        .risk-level-tool-tip {
                            margin: 0;
                        }
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
            }
            .inner-row {
                margin-bottom: 8px;
                display: flex;
                .title {
                    font-size: 14px;
                    color: #595959;
                    letter-spacing: 0;
                    font-weight: 400;
                    white-space: nowrap;
                    white-space: nowrap;
                }
                .msg {
                    font-size: 14px;
                    color: #262626;
                    letter-spacing: 0;
                    font-weight: 500;
                }
            }
        }
    }
    .modal-top-0 {
        display: flex;
        gap: 24px;
        margin-bottom: 24px;
        .modal-top-left-0 {
            height: 138px;
            background: rgba(255, 255, 255, 0.75);
            border: 2px solid #ffffff;
            border-radius: 4px;
            padding: 16px 24px;

            .left-top-0 {
                display: flex;
                margin-bottom: 4px;
                .left-top-img {
                    background-size: cover;
                    height: 20px;
                    width: 20px;
                    background-image: url('http://10.40.0.33:9001/file-storage/493888275024930816-source.png');
                }
                .left-top-msg {
                    font-size: 16px;
                    color: #262626;
                    letter-spacing: 0;
                    font-weight: 500;
                }
            }
            .left-bottom-0 {
                display: flex;
                gap: 16px;
                flex-direction: row;
                .new-bottom {
                    display: flex;

                    gap: 48px;
                }
                .bottom-left-0 {
                    width: 55%;
                    display: flex;
                    gap: 4px;
                    flex-direction: column;
                    .bottom-left-item {
                        display: flex;
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
                .bottom-right-0 {
                    flex: 1;
                    display: flex;
                    gap: 4px;
                    flex-direction: column;
                    position: relative;
                    .route-0 {
                        background-size: cover;
                        height: 76px;
                        width: 1px;
                        background-image: url('http://10.40.0.33:9001/file-storage/493904223171733504-source.png');
                        position: absolute;
                        top: 58%;
                        left: -24px;
                        transform: translate(-50%, -50%);
                    }
                    .bottom-right-item {
                        display: flex;
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
                .bottom-right-last-0 {
                    .bottom-right-item {
                        display: flex;
                        .title {
                            font-size: 14px;
                            color: #595959;
                            letter-spacing: 0;
                            font-weight: 400;
                            white-space: nowrap;
                        }
                        .msg {
                            font-size: 14px;
                            color: #262626;
                            letter-spacing: 0;
                            font-weight: 500;
                            white-space: nowrap;
                        }
                    }
                }
                .normal {
                    color: #262626;
                }
                .exceed {
                    color: #f5222d;
                }
            }
        }
        .modal-top-right-0 {
            width: 260px;
            height: 138px;
            background: rgba(255, 255, 255, 0.75);
            border: 2px solid #ffffff;
            border-radius: 4px;
            padding: 16px 24px;
            .right-top-0 {
                gap: 8px;
                display: flex;
                margin-bottom: 4px;
                align-items: center;
                .right-top-img {
                    background-size: cover;
                    height: 20px;
                    width: 20px;
                    background-image: url('http://10.40.0.33:9001/file-storage/493888385750362112-source.png');
                }
                .right-top-msg-0 {
                    font-size: 16px;
                    color: #262626;
                    letter-spacing: 0;
                    font-weight: 500;
                }
            }
            .right-bottom-0 {
                display: flex;
                flex-direction: column;
                gap: 4px;
                .bottom-right-item-0 {
                    display: flex;
                    .title {
                        font-size: 14px;
                        color: #595959;
                        letter-spacing: 0;
                        font-weight: 400;
                        white-space: nowrap;
                    }
                    .msg {
                        font-size: 14px;
                        color: #262626;
                        letter-spacing: 0;
                        font-weight: 500;
                        white-space: nowrap;
                    }
                }
            }
        }
    }

    .kb-table-box-new:deep(.@{ant-prefix}-table-thead) > tr > th {
        background: #3875ff;
        color: #fff;
        font-weight: 600;
        padding: 0;
        border-right: 1px solid #d9d9d9 !important;
        position: relative;
    }
    .kb-table-box-new :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-family: arial, helvetica, 'microsoft yahei';
        font-weight: 400;
        color: #262626;
        border-bottom: 1px solid #d9d9d9;
        padding: 0 5px;
        word-break: break-all;
    }
    /*冯腾飞样式*/
</style>
